在python中优雅的使用ffmpeg:PyAV 您所在的位置:网站首页 python3 ffmpeg 在python中优雅的使用ffmpeg:PyAV

在python中优雅的使用ffmpeg:PyAV

2024-06-01 09:35| 来源: 网络整理| 查看: 265

ffmpeg是强大的多媒体处理工具,堪称多媒体处理的瑞士军刀,涵盖了大量的多媒体处理工具。但是ffmpeg是由纯C语言写成,对于python用户来说使用难度较高,为此今天向大家推荐一款在python中使用ffmpeg的开发包:PyAV

PyAV提供了ffmpeg的python接口,但实际是它只是使用ffmpeg做后端,使用Cython封装了ffmpeg的接口,所以实际调用的还是ffmpeg。

PyAV安装

PyAV是跨平台的,可以根据自己的环境和平台选择安装。

Windows安装PyAV:

在Windows下安装PyAV可以参照博客https://blog.csdn.net/Dillon2015/article/details/91358179

Mac OS X和Ubuntu上安装PyAV:

在Mac OS X和Ubuntu上安装PyAV可以参考官网安装方法

PyAV使用

PyAV提供了非常方便的接口使开发者不需要太关注底层细节。

视频分割为独立的帧

有的时候做处理时需要将一段视频按帧分成一张张图像,在ffmpeg命令行中只需要一条命令:

ffmpeg –i test.avi –r 1 –f image2 image-%3d.jpeg

-r表示每秒提取图像的数量,如果等于帧率则会将所有帧都提取出来。

在PyAV中实现同样的功能也很简单,

import av ​ container = av.open(path_to_video) #path_to_video是你视频的路径 for frame in container.decode(video=0):    frame.to_image().save('frame-%04d.jpg' % frame.index) 保存关键帧

对于一个视频序列来说并不是所有帧都一样,因为视频编码在进行帧间预测时会出现相互参考的情况,如果一帧的参考帧丢失或损坏了那么这一帧就无法正确解码,所以对于那些用于被参考的帧就相对更重要了。

在av.video.frame.VideoFrame类中有一个属性key_frame用以表示该帧是否是关键帧。

import av import av.datasets ​ container = av.open(path_to_video) # Signal that we only want to look at keyframes. stream = container.streams.video[0] stream.codec_context.skip_frame = 'NONKEY' ​ for frame in container.decode(stream):    # We use `frame.pts` as `frame.index` won't make must sense with the `skip_frame`.    frame.to_image().save(        'night-sky.{:04d}.jpg'.format(frame.pts),        quality=80,   )

在以上代码中跳过了非关键帧,将所有关键帧保存下来。

视频转封装

视频转封装就是改变视频的封装格式而不改变其中视频流、音频流等的编码方式,例如从mp4->mkv

过程如下:

 

import av import av.datasets ​ input_ = av.open(path_to_video) output = av.open('remuxed.mkv', 'w') ​ # Make an output stream using the input as a template. This copies the stream # setup from one to the other. in_stream = input_.streams.video[0] out_stream = output.add_stream(template=in_stream) ​ for packet in input_.demux(in_stream):    # We need to skip the "flushing" packets that `demux` generates.    if packet.dts is None:        continue ​    # We need to assign the packet to the new stream.    packet.stream = out_stream    output.mux(packet) ​ output.close() 生成视频

PyAV还可以和numpy配合使用,直接将ndarray转换成视频帧,使得对帧的操作更加灵活和方便。

from __future__ import division ​ import numpy as np ​ import av ​ duration = 4 fps = 24 total_frames = duration * fps container = av.open('test.mp4', mode='w') stream = container.add_stream('mpeg4', rate=fps) stream.width = 480 stream.height = 320 stream.pix_fmt = 'yuv420p' ​ for frame_i in range(total_frames):    img = np.empty((480, 320, 3))    img[:, :, 0] = 0.5 + 0.5 * np.sin(2 * np.pi * (0 / 3 + frame_i / total_frames))    img[:, :, 1] = 0.5 + 0.5 * np.sin(2 * np.pi * (1 / 3 + frame_i / total_frames))    img[:, :, 2] = 0.5 + 0.5 * np.sin(2 * np.pi * (2 / 3 + frame_i / total_frames)) ​    img = np.round(255 * img).astype(np.uint8)    img = np.clip(img, 0, 255) ​    frame = av.VideoFrame.from_ndarray(img, format='rgb24')    for packet in stream.encode(frame):        container.mux(packet) ​ #Flush stream for packet in stream.encode():    container.mux(packet) ​ #Close the file container.close()

以上代码生成了一段480x320帧率24fps的视频。

小结

PyAV还要更多更强大的功能,感兴趣的小伙伴可以自己安装试试哦。

感兴趣的请关注微信公众号Video Coding

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有